package com.zzb.weixin;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.zzb.util.ReadPropertiesUtil;
import com.zzb.util.SecurityUtil;
import com.zzb.weixin.constant.Constant.WXLang;
import com.zzb.weixin.constant.Constant.WXMediaType;
import com.zzb.weixin.constant.Constant.WXOauthScope;
import com.zzb.weixin.constant.WXConfigName;
import com.zzb.weixin.constant.WXJsonName;
import com.zzb.weixin.exception.WeiXinException;
import com.zzb.weixin.json.JsonArray;
import com.zzb.weixin.json.JsonObject;
import com.zzb.weixin.model.AccessToken;
import com.zzb.weixin.model.OauthToken;
import com.zzb.weixin.model.UploadMsg;
import com.zzb.weixin.model.QRcode.QRCodeInfo;
import com.zzb.weixin.model.QRcode.QRCodeTicketInfo;
import com.zzb.weixin.model.menu.Menu;
import com.zzb.weixin.model.msg.basic.Msg;
import com.zzb.weixin.model.msg.mcs.CSRecordPageInfo;
import com.zzb.weixin.model.msg.mcs.CSResponseInfo;
import com.zzb.weixin.model.msg.send.Article;
import com.zzb.weixin.model.msg.send.GroupSendMsg;
import com.zzb.weixin.model.msg.send.OpenIdsSendMsg;
import com.zzb.weixin.model.msg.send.SendMsg;
import com.zzb.weixin.model.msg.send.SendResultMsg;
import com.zzb.weixin.model.msg.send.Video;
import com.zzb.weixin.model.msg.template.TemplateMsg;
import com.zzb.weixin.model.user.Group;
import com.zzb.weixin.model.user.WeiXinUser;
import com.zzb.weixin.model.user.WeiXinUserIdList;

public class WeiXinService {

	private static ReadPropertiesUtil readPropertiesUtil = new ReadPropertiesUtil(
			"config.properties");
	private static String appId = "";
	private static String appSecret = "";

	static {
		appId = readPropertiesUtil.getProperties(WXConfigName.APP_ID);
		appSecret = readPropertiesUtil.getProperties(WXConfigName.APP_SECRET);
	}
	private static AccessToken accessToken = null;

	/**
	 * 验证消息真实性
	 * @param token 用户令牌
	 * @param timestamp 时间戳
	 * @param nonce 随机数
	 * @param signature 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
	 * @return
	 */
	public static boolean check(String token, String timestamp, String nonce,
			String signature) {
		List<String> list = new ArrayList<String>(3);
		list.add(token);
		list.add(timestamp);
		list.add(nonce);
		Collections.sort(list);// 排序
		String tmpStr = new SecurityUtil().encode(list.get(0) + list.get(1)
				+ list.get(2), SecurityUtil.SHA_1);// SHA-1加密
		if (tmpStr.equals(signature)) {
			return true;
		}
		return false;
	}
	private static String getAccessTokenString() throws WeiXinException {
		if (accessToken == null || accessToken.isExpires()) {
			synchronized (WeiXinService.class) {
				if (accessToken == null || accessToken.isExpires()) {
					setAccessToken(createAccessToken());
				}
			}
		}
		return getAccessToken().getAccessToken();
	}

	/**
	 * 获取accessToken对象 appid appsecret 将从配置文件中读取
	 * 
	 * @return
	 * @throws WeiXinException
	 *             微信错误信息对象
	 */
	public static AccessToken createAccessToken() throws WeiXinException {
		return createAccessToken(appId, appSecret);
	}

	/**
	 * 获取accessToken对象
	 * 
	 * @param appId
	 * @param appSecret
	 * @return
	 * @throws WeiXinException
	 */
	public static AccessToken createAccessToken(String appId, String appSecret)
			throws WeiXinException {
		return new AccessToken(WeiXinApi.getAccessToken(appId, appSecret));
	}

	/**
	 * 如果公众号基于安全等考虑，需要获知微信服务器的IP地址列表，以便进行相关限制，可以通过该接口获得微信服务器IP地址列表。
	 * 
	 * @param accessToken
	 *            公众号的access_token
	 * @return
	 * @throws WeiXinException
	 */
	public static List<String> getIPList(String accessToken)
			throws WeiXinException {
		return getIPListAsJson(accessToken);
	}

	/**
	 * 如果公众号基于安全等考虑，需要获知微信服务器的IP地址列表，以便进行相关限制，可以通过该接口获得微信服务器IP地址列表。
	 * 
	 * @return
	 * @throws WeiXinException
	 */
	public static List<String> getIPList() throws WeiXinException {
		return getIPList(getAccessTokenString());
	}

	/**
	 * 如果公众号基于安全等考虑，需要获知微信服务器的IP地址列表，以便进行相关限制，可以通过该接口获得微信服务器IP地址列表。
	 * 
	 * @param accessToken
	 * @return
	 * @throws WeiXinException
	 */
	public static List<String> getIPListAsJson(String accessToken)
			throws WeiXinException {
		return WeiXinApi.getIPListAsJson(accessToken)
				.getAsJsonArray(WXJsonName.IP_LIST).getAsStringList();
	}

	/**
	 * 如果公众号基于安全等考虑，需要获知微信服务器的IP地址列表，以便进行相关限制，可以通过该接口获得微信服务器IP地址列表。
	 * 
	 * @return
	 * @throws WeiXinException
	 */
	public static List<String> getIPListAsJson() throws WeiXinException {
		return getIPListAsJson(getAccessTokenString());
	}

	/**
	 * 公众号可调用本接口来上传图片、语音、视频等文件到微信服务器，上传后服务器会返回对应的media_id，
	 * 公众号此后可根据该media_id来获取多媒体。请注意，media_id是可复用的，调用该接口需http协议。
	 * 
	 * @param file
	 * @param type
	 * @param accessToken
	 * @return
	 * @throws WeiXinException
	 */
	public static UploadMsg uploadMedia(File file, WXMediaType type,
			String accessToken) throws WeiXinException {
		JsonObject jo = WeiXinApi.uploadMedia(file, type, accessToken);
		return new UploadMsg(jo);
	}

	/**
	 * 公众号可调用本接口来上传图片、语音、视频等文件到微信服务器，上传后服务器会返回对应的media_id，
	 * 公众号此后可根据该media_id来获取多媒体。请注意，media_id是可复用的，调用该接口需http协议。
	 * 
	 * @param file
	 * @param type
	 * @return
	 * @throws WeiXinException
	 */
	public static UploadMsg uploadMedia(File file, WXMediaType type)
			throws WeiXinException {
		return uploadMedia(file, type, getAccessTokenString());
	}

	/**
	 * 公众号可调用本接口来获取多媒体文件。请注意，视频文件不支持下载，调用该接口需http协议。 文件名为系统默认文件名,
	 * 
	 * @param filepath
	 *            - 文件路径
	 * @param mediaId
	 * @param accessToken
	 * @throws WeiXinException
	 */
	public static File downloadMedia(String filepath, String mediaId,
			String accessToken) throws WeiXinException {
		return WeiXinApi.downloadMedia(filepath, mediaId, accessToken);
	}

	/**
	 * 公众号可调用本接口来获取多媒体文件。请注意，视频文件不支持下载，调用该接口需http协议。 文件名为系统默认文件名,
	 * 
	 * @param filepath
	 *            - 文件路径
	 * @param mediaId
	 * @param accessToken
	 * @throws WeiXinException
	 */
	public static File downloadMedia(String filepath, String mediaId)
			throws WeiXinException {
		return downloadMedia(filepath, mediaId, getAccessTokenString());
	}

	/**
	 * 发送客服消息
	 * 
	 * @param accessToken
	 * @param msg
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean sendCustomMsg(String accessToken, Msg msg)
			throws WeiXinException {
		WeiXinApi.sendCustomMsg(accessToken, msg.toJson());
		return true;
	}

	/**
	 * 发送客服消息
	 * 
	 * @param msg
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean sendCustomMsg(Msg msg) throws WeiXinException {
		return sendCustomMsg(getAccessTokenString(), msg);
	}

	/**
	 * 上传群发消息的图文消息素材
	 * 
	 * @param accessToken
	 * @param articles
	 * @return
	 * @throws WeiXinException
	 */
	public static UploadMsg uploadSendNews(String accessToken,
			List<Article> articles) throws WeiXinException {
		if (articles != null && articles.size() > 0) {
			JsonObject jo = new JsonObject();
			JsonArray ja = new JsonArray();
			for (Article article : articles) {
				ja.add(article.toJson());
			}
			jo.put(WXJsonName.ARTICLES, ja);
			jo = WeiXinApi.uploadNews(accessToken, jo);
			return new UploadMsg(jo);
		}
		throw new WeiXinException("99999", "不合法的图文信息记录数量");
	}

	/**
	 * 上传群发消息的图文消息素材
	 * 
	 * @param articles
	 * @return
	 * @throws WeiXinException
	 */
	public static UploadMsg uploadSendNews(List<Article> articles)
			throws WeiXinException {
		return uploadSendNews(getAccessTokenString(), articles);
	}

	/**
	 * 上传视频供群发消息使用
	 * 
	 * @param accessToken
	 * @param video
	 * @return
	 * @throws WeiXinException
	 */
	public static UploadMsg uploadSendVideo(String accessToken, Video video)
			throws WeiXinException {
		if (video != null) {
			JsonObject jo = video.toJson();
			jo = WeiXinApi.uploadNews(accessToken, jo);
			return new UploadMsg(jo);
		}
		throw new WeiXinException("99999", "不合法的图文信息记录数量");
	}

	/**
	 * 上传视频供群发消息使用
	 * 
	 * @param video
	 * @return
	 * @throws WeiXinException
	 */
	public static UploadMsg uploadSendVideo(Video video) throws WeiXinException {
		return uploadSendVideo(getAccessTokenString(), video);
	}

	/**
	 * 群发消息
	 * 
	 * @param accessToken
	 * @param sendMsg
	 * @return
	 * @throws WeiXinException
	 */
	public static SendResultMsg sendMore(String accessToken, SendMsg sendMsg)
			throws WeiXinException {
		if (sendMsg != null) {
			if (sendMsg instanceof GroupSendMsg) {
				return new SendResultMsg(WeiXinApi.sendAll(accessToken,
						sendMsg.toJson()));
			} else if (sendMsg instanceof OpenIdsSendMsg) {
				return new SendResultMsg(WeiXinApi.send(accessToken,
						sendMsg.toJson()));
			}
		}
		throw new WeiXinException("99999", "不合法的图文信息记录数量");
	}

	/**
	 * 群发消息
	 * 
	 * @param sendMsg
	 * @return
	 * @throws WeiXinException
	 */
	public static SendResultMsg sendMore(SendMsg sendMsg)
			throws WeiXinException {
		return sendMore(getAccessTokenString(), sendMsg);
	}

	/**
	 * 请注意，只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效，已经收到的用户，还是能在其本地看到消息卡片。
	 * 另外，删除群发消息只能删除图文消息和视频消息，其他类型的消息一经发送，无法删除。
	 * 
	 * @param accessToken
	 * @param msgId
	 * @return
	 * @throws WeiXinException
	 */
	public static SendResultMsg deleteMsg(String accessToken, String msgId)
			throws WeiXinException {
		JsonObject message = new JsonObject();
		message.put(WXJsonName.MSG_ID, msgId);
		return new SendResultMsg(WeiXinApi.delete(accessToken, message));
	}

	/**
	 * 请注意，只有已经发送成功的消息才能删除删除消息只是将消息的图文详情页失效，已经收到的用户，还是能在其本地看到消息卡片。
	 * 另外，删除群发消息只能删除图文消息和视频消息，其他类型的消息一经发送，无法删除。
	 * 
	 * @param msgId
	 * @return
	 * @throws WeiXinException
	 */
	public static SendResultMsg deleteMsg(String msgId) throws WeiXinException {
		return deleteMsg(getAccessTokenString(), msgId);
	}

	/**
	 * 发送模板消息
	 * 
	 * @param accessToken
	 * @param templateMsg
	 * @throws WeiXinException
	 * @return
	 */
	public static boolean sendTemplateMsg(String accessToken,
			TemplateMsg templateMsg) throws WeiXinException {
		WeiXinApi.sendTemplateMsg(accessToken, templateMsg.toJson());
		return true;
	}

	/**
	 * 发送模板消息
	 * 
	 * @param templateMsg
	 * @throws WeiXinException
	 * @return
	 */
	public static boolean sendTemplateMsg(TemplateMsg templateMsg)
			throws WeiXinException {
		return sendTemplateMsg(getAccessTokenString(), templateMsg);
	}

	/**
	 * 创建用户分组
	 * 
	 * @param accessToken
	 * @param group
	 * @return
	 * @throws WeiXinException
	 */
	public static Group createGroup(String accessToken, Group group)
			throws WeiXinException {
		return new Group(WeiXinApi.createGroup(accessToken, group.toJson()));
	}

	/**
	 * 创建用户分组
	 * 
	 * @param group
	 * @return
	 * @throws WeiXinException
	 */
	public static Group createGroup(Group group) throws WeiXinException {
		return createGroup(getAccessTokenString(), group);
	}

	/**
	 * 获取微信用户信息
	 * 
	 * @param accessToken
	 * @param openid
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUser getWeiXinUser(String accessToken, String openid,
			WXLang lang) throws WeiXinException {
		JsonObject jo = WeiXinApi.getWeiXinUser(accessToken, openid, lang);
		return new WeiXinUser(jo);
	}

	/**
	 * 获取微信用户信息
	 * 
	 * @param openid
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUser getWeiXinUser(String openid, WXLang lang)
			throws WeiXinException {
		return getWeiXinUser(getAccessTokenString(), openid, lang);
	}

	/**
	 * 获取用户分组列表
	 * 
	 * @param accessToken
	 * @return
	 * @throws WeiXinException
	 */
	public static List<Group> getGroups(String accessToken)
			throws WeiXinException {
		JsonObject jo = WeiXinApi.getGroups(accessToken);
		JsonArray ja = jo.getAsJsonArray(WXJsonName.GROUPS);
		if (ja != null) {
			List<Group> list = new ArrayList<Group>();
			for (int i = 0; i < ja.length(); i++) {
				list.add(new Group(ja.getAsJsonObject(i)));
			}
		}
		return null;
	}

	/**
	 * 获取用户分组列表
	 * 
	 * @return
	 * @throws WeiXinException
	 */
	public static List<Group> getGroups() throws WeiXinException {
		return getGroups(getAccessTokenString());
	}

	/**
	 * 根据用户openid获取用户所在分组id
	 * 
	 * @param accessToken
	 * @param openid
	 * @return
	 * @throws WeiXinException
	 */
	public static String getGroupByOpenID(String accessToken, String openid)
			throws WeiXinException {
		JsonObject jo = new JsonObject();
		jo.put(WXJsonName.OPEN_ID, openid);
		return WeiXinApi.getGroupByOpenID(accessToken, jo).getAsString(
				WXJsonName.GROUPID);
	}

	/**
	 * 根据用户openid获取用户所在分组id
	 * 
	 * @param openid
	 * @return
	 * @throws WeiXinException
	 */
	public static String getGroupByOpenID(String openid) throws WeiXinException {
		return getGroupByOpenID(getAccessTokenString(), openid);
	}

	/**
	 * 修改分组名
	 * 
	 * @param accessToken
	 * @param group
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean updateGroup(String accessToken, Group group)
			throws WeiXinException {
		WeiXinApi.updateGroup(accessToken, group.toJson());
		return true;
	}

	/**
	 * 修改分组名
	 * 
	 * @param group
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean updateGroup(Group group) throws WeiXinException {
		return updateGroup(getAccessTokenString(), group);
	}

	/**
	 * 修改用户分组
	 * 
	 * @param accessToken
	 * @param openid
	 *            用户id
	 * @param toGroupId
	 *            目标分组id
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean updateMemberGroup(String accessToken, String openid,
			String toGroupId) throws WeiXinException {
		JsonObject message = new JsonObject();
		message.put(WXJsonName.OPEN_ID, openid);
		message.put(WXJsonName.TO_GROUPID, toGroupId);
		WeiXinApi.updateMemberGroup(accessToken, message);
		return true;
	}

	/**
	 * 修改用户分组
	 * 
	 * @param openid
	 *            用户id
	 * @param toGroupId
	 *            目标分组id
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean updateMemberGroup(String openid, String toGroupId)
			throws WeiXinException {
		return updateMemberGroup(getAccessTokenString(), openid, toGroupId);
	}

	/**
	 * 修改用户备注名
	 * 
	 * @param accessToken
	 * @param openid
	 * @param remark
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean updateRemark(String accessToken, String openid,
			String remark) throws WeiXinException {
		JsonObject message = new JsonObject();
		message.put(WXJsonName.OPEN_ID, openid);
		message.put(WXJsonName.REMARK, remark);
		WeiXinApi.updateRemark(accessToken, message);
		return true;
	}

	/**
	 * 修改用户备注名
	 * 
	 * @param openid
	 * @param remark
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean updateRemark(String openid, String remark)
			throws WeiXinException {
		return updateRemark(getAccessTokenString(), openid, remark);
	}

	/**
	 * 获取用户信息
	 * 
	 * @param accessToken
	 * @param openid
	 * @param lang
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUser getUserInfo(String accessToken, String openid,
			WXLang lang) throws WeiXinException {
		return new WeiXinUser(WeiXinApi.getUserInfo(accessToken, openid, lang));
	}

	/**
	 * 获取用户信息
	 * 
	 * @param openid
	 * @param lang
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUser getUserInfo(String openid, WXLang lang)
			throws WeiXinException {
		return new WeiXinUser(WeiXinApi.getUserInfo(getAccessTokenString(),
				openid, lang));
	}

	/**
	 * 
	 * 获取关注者openip列表 当公众号关注者数量超过10000时，可通过填写next_openid的值，从而多次拉取列表的方式来满足需求。
	 * 具体而言，就是在调用接口时，将上一次调用得到的返回中的next_openid值，作为下一次调用中的next_openid值。
	 * 
	 * @param accessToken
	 * @param nextOpenId
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUserIdList getUserIdList(String accessToken,
			String nextOpenId) throws WeiXinException {
		return new WeiXinUserIdList(WeiXinApi.getUserOpenIDs(accessToken,
				nextOpenId));
	}

	/**
	 * 
	 * 获取关注者openip列表 当公众号关注者数量超过10000时，可通过填写next_openid的值，从而多次拉取列表的方式来满足需求。
	 * 具体而言，就是在调用接口时，将上一次调用得到的返回中的next_openid值，作为下一次调用中的next_openid值。
	 * 
	 * @param nextOpenId
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUserIdList getUserIdList(String nextOpenId)
			throws WeiXinException {
		return new WeiXinUserIdList(WeiXinApi.getUserOpenIDs(
				getAccessTokenString(), nextOpenId));
	}

	/**
	 * 获取oauth授权code页面url
	 * 
	 * @param appid
	 * @param returnUrl
	 *            授权后重定向的回调链接地址
	 * @param scope
	 * @param state
	 *            重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值
	 * @return
	 */
	public static String getCodeUrl(String appid, String returnUrl,
			WXOauthScope scope, String state) {
		return WeiXinUrlService.getGetCodeUrl(appid, returnUrl, scope, state);
	}

	/**
	 * 获取oauth授权code页面url
	 * 
	 * @param returnUrl
	 *            授权后重定向的回调链接地址
	 * @param scope
	 * @param state
	 *            重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值
	 * @return
	 */
	public static String getCodeUrl(String returnUrl, WXOauthScope scope,
			String state) {
		return WeiXinUrlService.getGetCodeUrl(appId, returnUrl, scope, state);
	}

	/**
	 * 获取网页授权token
	 * 
	 * @param appid
	 * @param secret
	 * @param code
	 * @return
	 * @throws WeiXinException
	 */
	public static OauthToken getOauthToken(String appid, String secret,
			String code) throws WeiXinException {
		return new OauthToken(
				WeiXinApi.getOauthAccessToken(appid, secret, code));
	}

	/**
	 * 获取网页授权token
	 * 
	 * @param code
	 * @return
	 * @throws WeiXinException
	 */
	public static OauthToken getOauthToken(String code) throws WeiXinException {
		return getOauthToken(appId, appSecret, code);
	}

	/**
	 * 刷新accessToken
	 * 
	 * @param appid
	 * @param refreshToken
	 * @return
	 * @throws WeiXinException
	 */
	public static OauthToken refushOauthToken(String appid, String refreshToken)
			throws WeiXinException {
		return new OauthToken(WeiXinApi.refreshOauthAccessToken(appid,
				refreshToken));
	}

	/**
	 * 刷新accessToken
	 * 
	 * @param refreshToken
	 * @return
	 * @throws WeiXinException
	 */
	public static OauthToken refushOauthToken(String refreshToken)
			throws WeiXinException {
		return new OauthToken(WeiXinApi.refreshOauthAccessToken(appId,
				refreshToken));
	}

	/**
	 * 使用oauth accessToken获取用户信息
	 * 
	 * @param accessToken
	 * @param openid
	 * @param lang
	 * @return
	 * @throws WeiXinException
	 */
	public static WeiXinUser getOauthUserInfo(String accessToken,
			String openid, WXLang lang) throws WeiXinException {
		return new WeiXinUser(WeiXinApi.getOauthUserInfo(accessToken, openid,
				lang));
	}

	/**
	 * 检查 oauth accessToken是否有效
	 * 
	 * @param accessToken
	 * @param openid
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean checkOauthAccessToken(String accessToken,
			String openid) throws WeiXinException {
		WeiXinApi.checkOauthAccessToken(accessToken, openid);
		return true;
	}

	/**
	 * 创建菜单
	 * 
	 * @param accessToken
	 * @param menu
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean createMenu(String accessToken, Menu menu)
			throws WeiXinException {
		WeiXinApi.createMenu(accessToken, menu.toJson());
		return true;
	}

	/**
	 * 创建菜单
	 * 
	 * @param menu
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean createMenu(Menu menu) throws WeiXinException {
		WeiXinApi.createMenu(getAccessTokenString(), menu.toJson());
		return true;
	}

	/**
	 * 查询菜单
	 * 
	 * @param accessToken
	 * @return
	 * @throws WeiXinException
	 */
	public static Menu getMenu(String accessToken) throws WeiXinException {
		return new Menu(WeiXinApi.getMenu(accessToken));
	}

	/**
	 * 查询菜单
	 * 
	 * @return
	 * @throws WeiXinException
	 */
	public static Menu getMenu() throws WeiXinException {
		return new Menu(WeiXinApi.getMenu(getAccessTokenString()));
	}

	/**
	 * 删除自定义菜单
	 * 
	 * @param accessToken
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean deleteMenu(String accessToken) throws WeiXinException {
		WeiXinApi.deleteMenu(accessToken);
		return true;
	}

	/**
	 * 删除自定义菜单
	 * 
	 * @return
	 * @throws WeiXinException
	 */
	public static boolean deleteMenu() throws WeiXinException {
		WeiXinApi.deleteMenu(getAccessTokenString());
		return true;
	}

	/**
	 * 创建二维码
	 * 
	 * @param accessToken
	 * @param codeInfo
	 * @return
	 * @throws WeiXinException
	 */
	public static QRCodeTicketInfo createQRcode(String accessToken,
			QRCodeInfo codeInfo) throws WeiXinException {
		return new QRCodeTicketInfo(WeiXinApi.createQrcode(accessToken,
				codeInfo.toJson()));
	}

	/**
	 * 创建二维码
	 * 
	 * @param codeInfo
	 * @return
	 * @throws WeiXinException
	 */
	public static QRCodeTicketInfo createQRcode(QRCodeInfo codeInfo)
			throws WeiXinException {
		return new QRCodeTicketInfo(WeiXinApi.createQrcode(
				getAccessTokenString(), codeInfo.toJson()));
	}

	/**
	 * 获取获取二维码的url
	 * 
	 * @param ticket
	 * @return
	 */
	public static String getQRCodeUrl(String ticket) {
		return WeiXinApi.getGetQRcodeUrl(ticket);
	}

	/**
	 * 下载二维码
	 * 
	 * @param ticket
	 * @param filepath
	 * @param fileName
	 * @return
	 */
	public static File downloadQRCode(String ticket, String filepath,
			String fileName) {
		return WeiXinApi.downLoadFile(getQRCodeUrl(ticket), filepath, fileName);
	}

	/**
	 * 获取短连接
	 * 
	 * @param accessToken
	 * @param longUrl
	 * @return
	 * @throws WeiXinException
	 */
	public static String getShortUrl(String accessToken, String longUrl)
			throws WeiXinException {
		return WeiXinApi.getShortUrl(accessToken, longUrl).getAsString(
				WXJsonName.SHORT_URL);
	}

	/**
	 * 获取短连接
	 * 
	 * @param longUrl
	 * @return
	 * @throws WeiXinException
	 */
	public static String getShortUrl(String longUrl) throws WeiXinException {
		return WeiXinApi.getShortUrl(getAccessTokenString(), longUrl)
				.getAsString(WXJsonName.SHORT_URL);
	}

	/**
	 * 获取客服消息列表
	 * 
	 * @param accessToken
	 * @param pageInfo
	 * @return
	 * @throws WeiXinException
	 */
	public static List<CSResponseInfo> getCSRecord(String accessToken,
			CSRecordPageInfo pageInfo) throws WeiXinException {
		JsonArray ja = WeiXinApi.getCSRecord(accessToken, pageInfo.toJson())
				.getAsJsonArray(WXJsonName.RECORD_LIST);
		List<CSResponseInfo> list = new ArrayList<CSResponseInfo>();
		for (int i = 0; i < ja.length(); i++) {
			list.add(new CSResponseInfo(ja.getAsJsonObject(i)));
		}
		return list;
	}

	/**
	 * 获取客服消息列表
	 * 
	 * @param pageInfo
	 * @return
	 * @throws WeiXinException
	 */
	public static List<CSResponseInfo> getCSRecord(CSRecordPageInfo pageInfo)
			throws WeiXinException {
		JsonArray ja = WeiXinApi.getCSRecord(getAccessTokenString(),
				pageInfo.toJson()).getAsJsonArray(WXJsonName.RECORD_LIST);
		List<CSResponseInfo> list = new ArrayList<CSResponseInfo>();
		for (int i = 0; i < ja.length(); i++) {
			list.add(new CSResponseInfo(ja.getAsJsonObject(i)));
		}
		return list;
	}

	public static String getAppId() {
		return appId;
	}

	public static void setAppId(String appId) {
		WeiXinService.appId = appId;
	}

	public static String getAppSecret() {
		return appSecret;
	}

	public static void setAppSecret(String appSecret) {
		WeiXinService.appSecret = appSecret;
	}

	public static AccessToken getAccessToken() {
		return accessToken;
	}

	public static void setAccessToken(AccessToken accessToken) {
		WeiXinService.accessToken = accessToken;
	}
}
